package br.siagefi.dao;

import br.siagefi.infra.JPAUtil;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;

//Aqui é onde trabalha a minha DAO Genérica, ela funcionará para todos os modelos
//e será instancia com nome T
public class DAO<T> implements Serializable{
    
    private final Class<T> classe;

    public DAO(Class<T> classe) {
        this.classe = classe;
    }
    
    public void adiciona(T t){
        EntityManager em = new JPAUtil().getEntityManager();
        em.getTransaction().begin();
        
        em.persist(t);
        
        em.getTransaction().commit();
        em.close();
    }
    
    public void remove(T t){
        EntityManager em = new JPAUtil().getEntityManager();
        em.getTransaction().begin();
        
        em.remove(em.merge(t));
        
        em.getTransaction().commit();
        em.close();

    }
    
    public void atualiza(T t){
        EntityManager em = new JPAUtil().getEntityManager();
        em.getTransaction().begin();
        
        em.merge(t);
        
        em.getTransaction().commit();
        em.close();
    }
    
    public List<T> listaTodos(){
        EntityManager em = new JPAUtil().getEntityManager();
        CriteriaQuery<T> query = em.getCriteriaBuilder().createQuery(classe);
        query.select(query.from(classe));
        
        List<T> lista = em.createQuery(query).getResultList();
        em.close();
        return lista;
    }
    
    public T buscaPorId(Long id){
        EntityManager em = new JPAUtil().getEntityManager();
        T instancia = em.find(classe, id);
        em.close();
        return instancia;
    }
    
    public int contaTodos() {
        EntityManager em = new JPAUtil().getEntityManager();
        long result = (Long) em.createQuery("select count(n) from " + classe.getName() + " n").getSingleResult();
	em.close();
        
        return (int) result;
	}
    
    public List<T> listaTodosPaginada(int firstResult, int maxResults){
        EntityManager em = new JPAUtil().getEntityManager();
        CriteriaQuery<T> query = em.getCriteriaBuilder().createQuery(classe);
        query.select(query.from(classe));
        
        List<T> lista = em.createQuery(query).setFirstResult(firstResult).
                setMaxResults(maxResults).getResultList();
        em.close();
        
        return lista;
    }
          
    public List<T> buscaPorNome(String nome){
        EntityManager em = new JPAUtil().getEntityManager();
        String jpql = "select b from Banco b where "
                + "lower(b.nome) like :nome order by b.nome";
    
        em.close();
        
        return em.createQuery(jpql, classe)
                .setParameter("nome", nome + "%").getResultList();
    }

    public List<T> consultar(String namedQuery, Object... parameters ){
        EntityManager em = new JPAUtil().getEntityManager();
        
        Query query = em.createNamedQuery(namedQuery, classe);
        if(parameters != null){
            for(int i = 0; i < parameters.length; i++){
                query.setParameter(i+1, parameters[i]);
            }
        }
        List<T> lista = query.getResultList();
        
        em.close();
        return lista;
    }
}
